3. Низови симбола (стрингови или ниске)¶
У овој глави ћемо
- упознати стрингове као низове карактера
- видети како се приступа елементима стринга и како се издвајају делови стринга, и
- упознати основне операције са стринговима.
3.1. Стрингови (ниске)¶
Иако су настали као машине за обраду нумеричких података рачунари су доживели врхунас свог успеха када се схватило да они могу да обрађују и симболичке податке. Обрада симболичких података данас представља доминантан начин употребе рачунара.
Стринг је реч кнјижевног енглеског језика (енгл. string) чије основно значење је "објекти исте врсте нанизани на нит". Зато се стрингови често на српском зову и ниске. У Пајтону стринг је низ симбола. На пример, ово су стрингови:
"Zdravo! Kako si?"
'Основна школа "Јован Јовановић-Змај"'
":-)"
''
""
Видимо да се стрингови пишу тако што се између апострофа или наводника (свеједно је) наведе произвољан низ симбола. Последња два примера нам показују како изгледа празан стринг, односно, стринг који нема ниједно слово. Други пример нам показује како да се снађемо ако стринг треба да садржи наводнике: просто га оградимо апострофима.
Број симбола у стрингу се зове дужина стринга. Дужине стрингова из претходног примера су, редом, 16, 36, 3, 0 и 0.
Стрингове додељујемо променљивим као што смо и навикли, исписујемо их командом print
, а учитавамо командом input
. Команда input
сачека да корисник унесе низ симбола и да на крају притисне [ENTER]. Она потом врати све симболе које је корисник унео као један низ симбола (такорећи стринг). На пример:
print("Unesi svoje ime, prvo u nominativu pa onda u vokativu")
ime = input("nominativ: ")
ime_v = input("vokativ: ")
print("Aha! Znao sam!")
print("Ti se zoveš", ime)
print("Zdravo,", ime_v)
Уграђена функција len
враћа дужину стринга и користи се овако:
print("Ti se zoveš", ime, "i tvoje ime ima", len(ime), "slova")
Пример. Написати Пајтон програм који утврђује колико пута се неки симбол јавља у унетом стрингу.
print("Utvrdjujemo koliko puta se neki simbol javlja u unetom stringu")
c = input("Unesi simbol: ")
s = input("Unesi string: ")
broj = 0
for x in s:
if x == c:
broj += 1
print("Simbol", c, "se u unetom stringu javlja", broj, "puta")
Конструкција for x in s
прође кроз цео стринг s
слово по слово, па за свако појављивање симбола c
увећамо бројач за 1.
Пример. Написати Пајтон програм који утврђује да ли је у датом стрингу број отворених заграда (
једнак броју затворених заграда )
.
s = input("Unesi string: ")
br_otvorenih = 0
br_zatvorenih = 0
for x in s:
if x == "(": br_otvorenih += 1
if x == ")": br_zatvorenih += 1
if br_otvorenih == br_zatvorenih:
print("isti je broj otvorenih i zatvorenih zagrada")
else:
print("nije isti broj otvorenih i zatvorenih zagrada")
3.2. Приступање елементима стринга и деловима стринга¶
Пошто је стринг низ симбола могуће је приступити појединачним симболима у стрингу, али и деловима стринга.
Стринг је, дакле, низ кућица. У сваку кућицу је уписан таћно један симбол и свака кућица има кућни број. Као и раније, кућни бројеви крећу од нуле. На пример, ако ставимо
s = "Popokatepetl"
онда је
s[4]
док је
s[0]
Инересантно је (а касније ћемо видети да је и корисно!) то што низови у Пајтону имају и негативне коефицијенте. Последња кућица у низу има индекс -1 ("први од краја"), претпоследња -2 ("други од краја") и тако даље. Зато је:
s[-1]
s[-5]
Из стринга можемо лако да издвојимо његове делове употребом конструкције: $$ \mathtt{s[} m : n \mathtt{]} $$ која издваја део стринга који почиње од кућице са редним бројем $m$ и завршава се са кућицом чији редни број је $n - 1$ (обрати пажњу: не иде до $n$, већ до кућице пре). На ово ћемо морати мало да се привикнемо. На пример,
s[2:5]
Дакле, из стринга s смо издвојили симболе s[2], s[3] и s[4], односно, кренули смо од кућице број 2 и завршили непосредно пре 5. кућице.
Ако желимо да издвојимо део стринга који креће од 6. кућице и иде до краја стринга, написаћемо
s[6:]
С друге стране, ако желимо да издвојимо део стринга који креће од пошетка стринга и иде до 6. кућице (укљућујући и њу) написаћемо:
s[:7]
Не смемо заборавити да се кућица чији кућни број је наведен иза двотачке не укључује у сегмент!
Издвајање делова стринга у комбинацији са негативним индексима нам омогућује да концизно запишемо веома корисне конструкције. Рецимо, последња четири елемента стринга добијамо овако:
s[-4:]
што је концизан запис за део стринга "од -4. кућице па до краја". С друге стране, "све осим последња два" можемо да запишемо овако:
s[:-2]
Пример. Написати Пајтон функцију prebroj_podstr(p, s)
која утврђује колико пута се стринг p
јавља као подстринг стринга s.
def prebroj_podstr(p, s):
broj = 0
n = len(p)
for i in range(len(s) - n + 1):
if p == s[i:i+n]:
broj += 1
return broj
Да погледамо како функција ради:
prebroj_podstr("bana", "oprobana torta od banana")
Пример. У сваком рачунарском систему се подаци пакују у фајлове (или датотеке) и од самих почетака рачунарске ере постоји обичај да се име фајла организује тако да последњих неколико симбола у имену фајла означава тип података који је у том фајлу похрањен. Тај део имена фајла се обично одвоји тачком од остатка имена фајла и зове се екстензија. Рецимо:
Екстензија | Тип података |
---|---|
.txt | текстуална датотека |
.log | текстуална датотека |
.png | слика |
.jpg | слика |
.bmp | слика |
.mpg | видео |
.mp3 | звук |
Написати Пајтон програм који од корисника учитава име фајлса и на основу горње табеле одређује тип података који је података који је у њему похрањен. У случају да се екстензија имена фајла не налази у овој табели програм треба да пријави да се ради о непознатом типу података.
fajl = input("Unesi ime fajla: ")
ekstenzija = fajl[-4:] # uzimamo poslednja 4 simbola imena
if ekstenzija in [".txt", ".log"]:
print("tekstualni fajl")
elif ekstenzija in [".png", ".jpg", ".bmp"]:
print("slika")
elif ekstenzija == ".mpg":
print("video")
elif ekstenzija == ".mp3":
print("zvuk")
else:
print("Ovaj format mi nije poznat")
Пример. Написати Пајтон функцију broj_reci(s)
која у датом стрингу броји речи. Реч је непрекидан низ слова.
def broj_reci(s):
n = len(s)
broj = 0
for i in range(n-1):
if s[i].isalpha() and not s[i+1].isalpha():
broj += 1
if s[n-1].isalpha():
broj += 1
return broj
Напоменимо пре свега да уграђена функција isalpha()
проверава да ли је нешто слово ("припадник неког алфабета").
Функција broj_reci(s)
се ослања на једноставну идеју: када са слова пређемо на симбол који није слово, то је сигуран знак да смо управо детектовали једну реч и онда бројач увећавамо за 1. Ова стратегија ради за све речи у стрингу осим за последњу јер нам у том случају недостаје слово које је "окидач" за детектовање краја речи. Зато последња if
наредба проверава да ли је последњи симбол у стрингу слово, како би и последња реч била урачуната.
Ево неколико примера:
broj_reci("Ovo je samo primer")
broj_reci("Proba")
broj_reci("!!!!")
3.3. Операције са стринговима¶
У Пајтону, као и у већини модерних програмских језика, стрингови су непроменљиви (то својство се на енглеском зове immutability). На пример, нека је
s = "Banana"
Ако покушамо да променимо прво слово стринга на мало слово b
добићемо грешку:
s[0] = "b"
Зато трансформације са стринговима увек своде на то да се од старог стринга изгради нови стринг који има својства која желимо. Једна од основних операција коју при томе користимо је надовезивање стрингова или конкатенација. Операција надовезивања стрингова се означава знаком +
. На пример:
s = "Novi"
t = "Beograd"
s + t
Важно је напоменути да надовезивање стрингова ради на најједноставнији могући начин: просто дода један стринг на крај оног другог, без уметања празнина или неке друге врсте мудровања.
Користећи операцију надовезивања можемо стрингу додати неки други стринг на почетак или на крај. На пример:
s = "bana"
s = "opro" + s
s
s = "bana"
s = s + "na"
s
Још једна интересантна операција је множење стринга бројем. На пример,
"Mir! " * 3
Пример. Исписати (за казну :-)) 100 пута: "Ученици не смеју да се гађају кредом!"
"Ученици не смеју да се гађају кредом!" * 100
Пример. Написати Пајтон функцију која обрће стринг.
def obrni_string(s):
novi = ""
for x in s:
novi = x + novi
return novi
Ова функција од стринга s
у променљивој novi
изгради нови стринг који садржи иста слова као и стринг s
, али у обрнутом редоследу. На почетку поставимо стринг novi
на празан стринг. Потом у циклусу слова стринга s
додајемо на стринг novi
, али једно по једно на почетак стринга novi
. Тако прво слово стринга s
постаје последње слово стринга novi
, док последње слово стринга s
на крају буде прво слово стринга novi
. Другим речима, у стрингу novi
изградимо слово по слово обрнуту верзију стринга s
.
Погледајмо на пар примера како ова функција ради:
obrni_string("Proba")
obrni_string("ana voli milovana")
Пример. Написати Пајтон програм који проверава да ли је дата реченица палиндром. Приликом провере треба игнорисати празинине и величину слова. На пример, следеће реченице су палиндроми:
Ана воли Милована!
Сир има мирис?
Сава зидар ради за вас
Маја са Недом оде на сајам.
Решење. У решењу овог примера ћемо користити уграђену функцију isaplha()
која проверава да ли је нешто слово, као и уграђену функцију lower()
која од стринга прави нови у коме су сва слова мала.
s = input("Unesi string: ")
novi = ""
obrnut = ""
for x in s.lower():
if x.isalpha():
novi = novi + x
obrnut = x + obrnut
if novi == obrnut:
print("jeste palindrom")
else:
print("nije palindrom")
3.4. Задаци¶
Задатак 1. Написати Пајтон програм који од корисника учитава стринг и онда утврђује број самогласника и број сугласника у том стрингу.
Задатак 2. Написати Пајтон функцију poslednja_rec(s)
која из датог стринга издваја последњу реч која је наведена у стрингу. Ако у стрингу не постоји ниједно слово функција треба да врати празан стринг. (Напомена: реч је непрекидан низ слова.)
Задатак 3. Написати пајтон функцију ispravi_interpunkciju(s)
која у датом стрингу додаје по једну празнину иза сваког знака интерпункције, али само ако је то потребно. На пример, за стринг
"Halo?Da? Ne.Ko je to?"
функција треба да врати:
"Halo? Da? Ne. Ko je to?"
Задатак 4. Написати Пајтон функцију obrni_reci(s)
која од датог стринга прави нови у коме су речи послагане од последње према првој. На пример, за стринг
"Napisati program koji ispisuje reci unetog teksta u obrnutom poretku"
функција треба да врати:
"poretku obrnutom u teksta unetog reci ispisuje koji program Napisati"
Задатак 5*. Написати Пајтон функцију која проверава да ли су у датом стрингу заграде ( и ) балансиране. То значи да у стрингу имамо исти број отворених и затоврених заграда, и да не постоји почетни сегмент стринга у коме је број затворених заграда већи од броја отворених.
Задатак 6. Написати Пајтон функцију razmeni(s, din_za_1_eur)
која конвертује дати износ из динара у евре и обрнуто. Стринг s
садржи износ записан у облику $\langle \mathrm{broj} \rangle \langle \mathrm{valuta} \rangle$, на пример овако:
125 DIN
217.50 EUR
1527.99 DIN
50 EUR
док аргумент din_za_1_eur
представља вредност једног евра у динарима. Функција треба да врати стринг који има облик $\langle \mathrm{broj} \rangle \langle \mathrm{valuta} \rangle$. При томе ти могу од користи бити уграђене функције float
и str
. За неки стринг p
функција float(p)
враћа број који је записан стрингом p
игноришући при том празнине које се можда јављају у стрингу. На пример:
float(" 123.4 ")
С друге стране, функција str
од неког броја прави стринг који садржи његов запис. На пример:
str(2.89)
Функција razmeni
треба да ради овако:
razmeni("124.99 EUR", 117.90)
'14736.321 DIN'
razmeni("12000 DIN", 117.90)
'101.7811704 EUR'